{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modMessagesList;

interface

uses Classes, SysUtils;

type

   // il manque l'année dans la date
   TOGMessageDate = record
      Mois   : word;
      Jour   : word;
      Heure  : word;
      Minute : word;
      Seconde: word;
   end;

   TOGMessage = record
      // Nom de la checkbox
      CheckBox : string;          // clé unique

      Date     : string;

      // Date extraite du champ "Date"
      DateInt  : TOGMessageDate;

      // Comme il manque la date dans le champ date
      // on propose ici une ESTIMATION de la date
      // Cette date correspond à celle du champ "Date"
      // c'est à dire ajusté sur l'heure du serveur
      // il ne faut pas la comparer directement à l'heure locale
      // (il faut y ajouter le décalage serveur/local)
      DateEstimation: int64;

      Emetteur : string;
      Sujet    : string;
      Contenu  : string;

      // Seulement si c'est un rapport de combat
      RapportCombatLink: string;
   end;



    POGMessage = ^TOGMessage;
    TCollectionOGMessage = class(TList)
    private
       {--------------------------------------------------}
       {Elements spécialisés de la classes}


      
       {--------------------------------------------------}
       {Gestion des pointeurs}
       // Utilisé pour la propriété Itemx
       function GetItemx(Index: integer): TOGMessage;
    public
       procedure DuplicationZoneMemoireFromList(List: TCollectionOGMessage);


       {--------------------------------------------------}
       {Gestion des pointeurs}
       // *** Ajout de pointeurs
       // Renvoi le pointeur de l'élément ajouté
       function Add(Element: TOGMessage): POGMessage;
      
       // Simple ajout de pointeur
       procedure SimpleAdd(Pointeur: POGMessage);
      
       // Renvoi le pointeur de l'élément ajouté/modifié
       // Utilise Get_Index pour vérifier si l'élément doit être mis à jour
       function Add_Update(Element: TOGMessage): POGMessage;
      
      
       // *** Suppression de pointeur
       // Libère et supprime le pointeur Index
       // Renvoi True si réussit, False si hors limite ou erreur
       function Delete(Index: integer): boolean; overload;

       // Cherche Element avec Get_Index et supprime LE
       // PREMIER pointeur trouvé, renvoi True si réussit
       function Delete(Element: string): boolean; overload;

      
       // *** Effacement de la liste de pointeur
       procedure Clear; override;
      
      
       // *** Requete sur la liste de pointeur
       function Get_Index(const Element: string): integer;
       function Get_Pointeur(const Element: string): POGMessage;
       function Get_Item(Index: integer): TOGMessage;
       property Itemx[Index: integer]: TOGMessage read GetItemx;
      

       procedure SetURLOfPage(PageWeb: string);
      
       {--------------------------------------------------}
       {Procédures et fonctions spécialisées de la classes}
       // Destructeur
       destructor Destroy; override;
       constructor Create;

    end;


    function mmlIsValidDate(h: TOGMessageDate): boolean;
    function mmlParsingDate(str: string): TOGMessageDate;


implementation

uses sHTMLFonctions;

function mmlParsingDate(str: string): TOGMessageDate;
label lLastUnit;
const dFormat : PChar = 'm-d h:t:s';
var xPos: integer;
    s: string;
    sNombre: string;

    px: PChar;
    sx: PChar;
    bExit: boolean;
begin
     //  fr: 10-19 17:29:22
     // org: 10-20 11:21:24

     Result.Mois := 0;
     Result.Jour := 0;
     Result.Heure   := 0;
     Result.Minute  := 0;
     Result.Seconde := 0;

     bExit := false;


     px := dFormat;
     sx := PChar(str);

     sNombre := '';

     while (sx^ <> #0) do begin
        case sx^ of
            '0'..'9': begin
               // chiffre
               sNombre := sNombre + sx^;
            end;

            else begin
               // ce n'est pas un nombre

               if sNombre <> '' then begin

lLastUnit:
                  case px^ of
                     'm': Result.Mois    := StrToIntDef(sNombre, -1);
                     'd': Result.Jour    := StrToIntDef(sNombre, -1);
                     'h': Result.Heure   := StrToIntDef(sNombre, -1);
                     't': Result.Minute  := StrToIntDef(sNombre, -1);
                     's': Result.Seconde := StrToIntDef(sNombre, -1);
                  end;

                  if bExit then begin
                     exit;
                  end;
                  Inc(px);
                  sNombre := '';
               end;


               // séparateur, qui doit se trouver dans la chaine
               if px^ <> sx^ then begin
                  // erreur
                  exit;
               end;
               Inc(px);

            end;

        end;

        
        Inc(sx);
        if px^ = #0 then begin
           break;
        end;
     end;

     if px^ = #0 then begin
        // erreur...
        exit;
     end;

     // pour s'assurer que l'on est sur le dernier caractère
     Inc(px);

     if (sx^ = #0) and (px^ = #0) and (sNombre <> '') then begin
        // revient sur le dernier caractère
        Dec(px);
        bExit := true;
        goto lLastUnit;

     end;

end;

function mmlIsValidDate(h: TOGMessageDate): boolean;
begin
   Result := false;
   if (h.Mois < 1) or (h.Mois > 12) then begin
      exit;
   end;

   if (h.Jour < 1) or (h.Jour > 31) then begin
      exit;
   end;

   if (h.Heure < 0) or (h.Heure > 24) then begin
      exit;
   end;

   if (h.Minute < 0) or (h.Minute > 59) then begin
      exit;
   end;

   if (h.Seconde < 0) or (h.Seconde > 59) then begin
      exit;
   end;

   Result := true;

end;

{*******************************************************************************
 *******************************************************************************
 **               TCollectionOGMessage                                     **
 *******************************************************************************
 *******************************************************************************}


procedure TCollectionOGMessage.SetURLOfPage(PageWeb: string);
var i: integer;
    pe: POGMessage;
begin

    if Count = 0 then begin
       exit;
    end;

    for i := 0 to Count - 1 do begin
       pe := Items[i];

       if pe.RapportCombatLink <> '' then begin
          // c'est un rapport de combat
          pe.RapportCombatLink := sHTML_Get_URL_Lien(PageWeb, pe.RapportCombatLink);
       end;
    end;
end;


procedure TCollectionOGMessage.DuplicationZoneMemoireFromList(List: TCollectionOGMessage);
var i: integer;
    pe: POGMessage;
begin

     if List.Count = 0 then exit;

     for i := 0 to List.Count - 1 do begin
         pe := List.Items[i];

         // Duplique l'élément (ce n'est pas un simple ajout de pointeur)
         Add(pe^);
     end;

     
end;

constructor TCollectionOGMessage.Create;
begin
    
    // Héritage
    InHerited Create;
    
    
    
    // Code pour l'initialisation ici
    
    
end;

destructor TCollectionOGMessage.Destroy;
begin
    // Implémenter le code avant l'héritage de la méthode
    // C'est à dire ici
    
   
    // On appelle NOTRE clear qui lui-même appelle NOTRE Delete qui libère l'espace mémoire
    // avant d'enlever le pointeur de la TList
    // L'héritage de Destroy appelle Clear, mais es-ce le notre ou celui de la classe de base ?
    Clear;
    
    
    // Héritage
    InHerited Destroy;
end;


procedure TCollectionOGMessage.Clear;
var i: integer;
begin

    if Count > 0 then begin
        For i := Count -1 downto 0 do
            Delete(i);
    end;
    
    inherited Clear;
end;


function TCollectionOGMessage.Get_Pointeur(const Element: string): POGMessage;
var i: integer;
begin

   Result := nil;
   
   i := Get_Index(Element);
   if i < 0 then exit;
   Result := Items[i];

end;


function TCollectionOGMessage.Get_Index(const Element: string): integer;
var i: integer;
    xEle, xTest: string;
    pElement: POGMessage;
begin

   Result := -1;

   if Count <= 0 then exit;
   xEle := lowercase(Element);

   for i := 0 to Count - 1 do begin

      pElement := Items[i];          {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
      xTest := pElement^.CheckBox;        {### Neccessite adpation en fonction du type record  ### }
      xTest := lowercase(xTest);     {### ### ### ### ### ### ### ### ### ### ### ### ### ### }


      if xEle = xTest then begin
         Result := i;
         exit;
      end;
   end;


end;

function TCollectionOGMessage.Add_Update(Element: TOGMessage): POGMessage;
var i : integer;
begin
     
     Result := nil;
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     i := Get_Index(Element.CheckBox);        {### Neccessite adpation en fonction du type record  ### }
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     if i < 0 then begin 
        // L'élément n'existe pas, l'ajoute
        Result  := Add(Element);
     end else begin
        // L'élément existe déjà, le met à jour
        Result  := Items[i];     // Obtient le pointeur
        Result^ := Element;
     end;
     
end;




function TCollectionOGMessage.Get_Item(Index: integer): TOGMessage;
var pElement: POGMessage;
begin

     if Index < 0 then exit;
     if Index >= Count then exit;

     pElement := Items[Index];     // Obtient le pointeur
     Result := pElement^;

end;

function TCollectionOGMessage.Delete(Index: integer): boolean;
var pElement: POGMessage;
begin

    Result := false;

    if (Index < 0) or (Index >= Count) then
       // Hors limite
       exit;


    // Obtient le pointeur
    pElement := Items[Index];

    if pElement <> nil then
       // Libére la mémoire créée lors de l'ajout
       Dispose(pElement);

    // Supprime le pointeur de la liste
    inherited Delete(Index);

    // Met le resultat à True
    Result := true;

end;

function TCollectionOGMessage.Delete(Element: string): boolean;
var i : integer;
begin

    Result := false;
    i      := Get_Index(Element);

    if i >= 0 then begin
       // Element trouvé
       // Le supprime
       Delete(i);

       // Même si la suppression Echoue on renvoi True
       // Car l'élément a été trouvé
       Result := true;
    end;
end;


function TCollectionOGMessage.Add(Element: TOGMessage): POGMessage;
var pElement: POGMessage;
begin
    
    Result := nil;
    
    New(pElement);          // Créer l'espace mémoire requis
    pElement^ := Element;   // Recopie les données dans l'emplacement pointé
    
    try
       inherited Add(pElement);  // Ajoute le pointeur à la liste
       Result := pElement;
    except
       Result := nil;
    end;
    
    // Pour libérer la mémoire occupé par l'élément pointer:  Dispose(pElement);

end;

// Simple ajout de pointeur
procedure TCollectionOGMessage.SimpleAdd(Pointeur: POGMessage);
begin
    
    inherited Add(Pointeur);  // Ajoute le pointeur à la liste
    
end;

function TCollectionOGMessage.GetItemx(Index: integer): TOGMessage;
var pElement: POGMessage;
begin

   if Count < 0 then exit;
   if Index >= Count then exit;

   pElement := Items[Index];
   Result := pElement^;

end;


end.
